﻿Imports System
Imports System.Collections
Imports System.Collections.Generic
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Runtime.Serialization
Imports System.Security.Permissions
Imports System.Workflow.ComponentModel
Imports System.Xml

Namespace System.Workflow.ComponentModel.Serialization
    Public NotInheritable Class ActivitySurrogateSelector
        Inherits SurrogateSelector
        ' Methods
        <SecurityPermission(SecurityAction.LinkDemand, Flags:=SecurityPermissionFlag.SerializationFormatter)> _
        Public Overrides Function GetSurrogate(ByVal type As Type, ByVal context As StreamingContext, <Out> ByRef selector As ISurrogateSelector) As ISerializationSurrogate
            Dim flag As Boolean
            If (type Is Nothing) Then
                Throw New ArgumentNullException("type")
            End If
            selector = Me
            Dim activitySurrogate As ISerializationSurrogate = Nothing
            SyncLock ActivitySurrogateSelector.surrogateCache
                flag = ActivitySurrogateSelector.surrogateCache.TryGetValue(type, activitySurrogate)
            End SyncLock
            If flag Then
                If (Not activitySurrogate Is Nothing) Then
                    Return activitySurrogate
                End If
                Return MyBase.GetSurrogate(type, context, selector)
            End If
            If GetType(Activity).IsAssignableFrom(type) Then
                activitySurrogate = Me.activitySurrogate
            ElseIf GetType(ActivityExecutor).IsAssignableFrom(type) Then
                activitySurrogate = Me.activityExecutorSurrogate
            ElseIf GetType(IDictionary([Of] DependencyProperty, Object)).IsAssignableFrom(type) Then
                activitySurrogate = Me.dependencyStoreSurrogate
            ElseIf GetType(XmlDocument).IsAssignableFrom(type) Then
                activitySurrogate = Me.domDocSurrogate
            ElseIf (GetType(Queue) Is type) Then
                activitySurrogate = Me.queueSurrogate
            ElseIf (GetType(Guid) Is type) Then
                activitySurrogate = Me.simpleTypesSurrogate
            ElseIf GetType(ActivityBind).IsAssignableFrom(type) Then
                activitySurrogate = Me.objectSurrogate
            ElseIf GetType(DependencyObject).IsAssignableFrom(type) Then
                activitySurrogate = Me.objectSurrogate
            End If
            SyncLock ActivitySurrogateSelector.surrogateCache
                ActivitySurrogateSelector.surrogateCache.Item(type) = activitySurrogate
            End SyncLock
            If (Not activitySurrogate Is Nothing) Then
                Return activitySurrogate
            End If
            Return MyBase.GetSurrogate(type, context, selector)
        End Function


        ' Properties
        Public Shared ReadOnly Property [Default] As ActivitySurrogateSelector
            Get
                Return ActivitySurrogateSelector.defaultActivitySurrogateSelector
            End Get
        End Property


        ' Fields
        Private activityExecutorSurrogate As ActivityExecutorSurrogate = New ActivityExecutorSurrogate
        Private activitySurrogate As ActivitySurrogate = New ActivitySurrogate
        Private Shared defaultActivitySurrogateSelector As ActivitySurrogateSelector = New ActivitySurrogateSelector
        Private dependencyStoreSurrogate As DependencyStoreSurrogate = New DependencyStoreSurrogate
        Private dictionarySurrogate As DictionarySurrogate = New DictionarySurrogate
        Private domDocSurrogate As XmlDocumentSurrogate = New XmlDocumentSurrogate
        Private genericqueueSurrogate As GenericQueueSurrogate = New GenericQueueSurrogate
        Private listSurrogate As ListSurrogate = New ListSurrogate
        Private objectSurrogate As ObjectSurrogate = New ObjectSurrogate
        Private queueSurrogate As QueueSurrogate = New QueueSurrogate
        Private simpleTypesSurrogate As SimpleTypesSurrogate = New SimpleTypesSurrogate
        Private Shared surrogateCache As Dictionary([Of] Type, ISerializationSurrogate) = New Dictionary([Of] Type, ISerializationSurrogate)

        ' Nested Types
        Private NotInheritable Class ObjectSurrogate
            Implements ISerializationSurrogate
            ' Methods
            Public Sub GetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext)
                info.AddValue("type", obj.GetType)
                Dim names As String() = Nothing
                Dim serializableMembers As MemberInfo() = FormatterServicesNoSerializableCheck.GetSerializableMembers(obj.GetType, names)
                Dim objectData As Object() = FormatterServices.GetObjectData(obj, serializableMembers)
                info.AddValue("memberDatas", objectData)
                info.SetType(GetType(ObjectSerializedRef))
            End Sub

            Public Function SetObjectData(ByVal obj As Object, ByVal info As SerializationInfo, ByVal context As StreamingContext, ByVal selector As ISurrogateSelector) As Object
                Return Nothing
            End Function


            ' Nested Types
            <Serializable> _
            Private NotInheritable Class ObjectSerializedRef
                Implements IObjectReference, IDeserializationCallback
                ' Methods
                Private Sub System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(ByVal sender As Object) Implements IDeserializationCallback.OnDeserialization
                    If (Not Me.returnedObject Is Nothing) Then
                        Dim names As String() = Nothing
                        Dim serializableMembers As MemberInfo() = FormatterServicesNoSerializableCheck.GetSerializableMembers(Me.type, names)
                        FormatterServices.PopulateObjectMembers(Me.returnedObject, serializableMembers, Me.memberDatas)
                        Me.returnedObject = Nothing
                    End If
                End Sub

                Private Function System.Runtime.Serialization.IObjectReference.GetRealObject(ByVal context As StreamingContext) As Object Implements IObjectReference.GetRealObject
                    If (Me.returnedObject Is Nothing) Then
                        Me.returnedObject = FormatterServices.GetUninitializedObject(Me.type)
                    End If
                    Return Me.returnedObject
                End Function


                ' Fields
                Private memberDatas As Object()
                <NonSerialized> _
                Private returnedObject As Object
                Private type As Type
            End Class
        End Class
    End Class
End Namespace

